// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UIOrderTracker.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.Forge.UI.Forms
{
    #region Using Directives

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;

    using Org.OpenTrader.Framework.Enums;
    using Org.OpenTrader.Framework.Events;
    using Org.OpenTrader.Framework.Forge.DataCache;
    using Org.OpenTrader.Framework.Forge.Events;
    using Org.OpenTrader.Framework.Forge.Interfaces;
    using Org.OpenTrader.Framework.LinqKit;
    using Org.OpenTrader.Framework.UI.Forms;

    #endregion

    /// <summary>
    /// The ui order tracker.
    /// </summary>
    public partial class UIOrderTracker : UIControl
    {
        // Known orders
        #region Constants and Fields

        /// <summary>
        /// The current instrument.
        /// </summary>
        private IInstrument currentInstrument;

        /// <summary>
        /// The trackingCells.
        /// </summary>
        private IDictionary<Guid, IOrderTrackingCell> trackingCells = new Dictionary<Guid, IOrderTrackingCell>();

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="UIOrderTracker"/> class.
        /// </summary>
        public UIOrderTracker()
        {
            this.InitializeComponent();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets Instrument.
        /// </summary>
        public IInstrument Instrument
        {
            get
            {
                return this.currentInstrument;
            }

            set
            {
                if (this.currentInstrument != null)
                {
                    this.currentInstrument.OrderTrackingEventCB -= this.OnOrderTracking;
                    this.trackingCells.Clear();
                }

                this.currentInstrument = value;
                if (this.currentInstrument != null)
                {
                    // Start over
                    var allCells = PredicateBuilder.True<IOrderTrackingCell>();
                    foreach (var cell in this.currentInstrument.OrderTracker.GetTrackingCells(allCells))
                    {
                        this.trackingCells.Add(cell.Order.ID, cell);
                    }

                    this.currentInstrument.OrderTrackingEventCB += this.OnOrderTracking;

                    this.Refresh();
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The executions tooltip.
        /// </summary>
        /// <param name="execs">
        /// The execs.
        /// </param>
        /// <returns>
        /// The executions tooltip.
        /// </returns>
        private string ExecutionsTooltip(IExecution[] execs)
        {
            var s = string.Empty;
            foreach (var e in execs)
            {
                s += string.Format("{0} x {1} {2}\n", e.Price, e.Quantity, e.Counterparty);
            }

            return s;
        }

        /// <summary>
        /// The on order tracking.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="args">
        /// The args.
        /// </param>
        private void OnOrderTracking(object sender, OrderTrackingEventArgs args)
        {
            var cell = args.OrderTrackingCell;
            if (!this.trackingCells.ContainsKey(cell.Order.ID))
            {
                this.trackingCells.Add(cell.Order.ID, cell);
            }
        }

        /// <summary>
        /// The virtualgrid_ cell click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnVirtualgridCellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0 || e.RowIndex >= this.trackingCells.Keys.Count())
            {
                return;
            }

            if (e.ColumnIndex == 21 && this.virtualgrid[e.ColumnIndex, e.RowIndex].Value != null)
            {
                var cell = this.trackingCells[this.trackingCells.Keys.ElementAt(e.RowIndex)];
                if (cell != null)
                {
                    var ctrl = new UIManualOrder(cell.Order, cell.Tracker);
                    var form = ctrl.CreateContainingForm("Modify Order", EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);
                    form.Visibility = EUIFormVisibility.Show;
                }
            }
            else if (e.ColumnIndex == 22 && this.virtualgrid[e.ColumnIndex, e.RowIndex].Value != null)
            {
                // Cancel
                var cell = this.trackingCells[this.trackingCells.Keys.ElementAt(e.RowIndex)];
                if (cell != null)
                {
                    var parent = cell.Tracker;
                    if (parent != null)
                    {
                        parent.CancelOrder(cell.Order);
                    }
                }
            }
        }

        /// <summary>
        /// The virtualgrid_ ui grid query cell info.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnVirtualgridUIGridQueryCellInfo(object sender, VirtualGridEventArgs.QueryCellInfo e)
        {
            if (e.RowIndex < 0)
            {
                return;
            }

            // Order at that e.RowIndex
            var cell = this.trackingCells[this.trackingCells.Keys.ElementAt(e.RowIndex)];

            if (cell == null)
            {
                return;
            }

            // Related instrument
            var i = Singleton<DC>.Instance.GetInstrumentStaticDataFromCache(cell.Order.InstrumentID);

            // According the column display required data
            switch (e.ColumnIndex)
            {
                case 0: // code
                    e.Value = i.Code;
                    break;

                case 1: // scope
                    e.Value = i.TradingScope;
                    break;

                case 2: // type
                    e.Value = cell.Order.Type;
                    break;
                case 3: // way
                    e.Value = cell.Order.Way;
                    break;
                case 4: // qty
                    e.Value = cell.RequestedQuantity;
                    break;

                case 5: // price
                    e.Value = ForgePrettyPrinter.Prices.Format(cell.RequestedPrice, i.TickSizeRule.Tick(cell.RequestedPrice));
                    break;
                case 6: // send stamp
                    e.Value = PrettyPrinter.Timings.Format(cell.SendStamp);
                    break;
                case 7: // ack stamp
                    e.Value = PrettyPrinter.Timings.Format(cell.AckStamp);
                    break;
                case 8: // reject stamp
                    e.Value = PrettyPrinter.Timings.Format(cell.RejectStamp);
                    e.ToolTip = cell.RejectReason;
                    break;
                case 9: // cancel stamp
                    e.Value = PrettyPrinter.Timings.Format(cell.CancelAckStamp);
                    break;
                case 10: // modify stamp
                    e.Value = PrettyPrinter.Timings.Format(cell.ModifyAckStamp);
                    break;
                case 11: // fully executed
                    e.Value = cell.Executed;
                    break;
                case 12: // out report
                    e.Value = PrettyPrinter.Timings.Format(cell.OutReportStamp);
                    break;
                case 13: // last executed
                    e.Value = PrettyPrinter.Timings.Format(cell.LastExecutionStamp);
                    break;
                case 14: // #executions
                    e.Value = cell.Executions.Length;
                    e.ToolTip = this.ExecutionsTooltip(cell.Executions);
                    break;
                case 15: // Cancel Rejected
                    e.Value = cell.CancelRejected;
                    break;
                case 16: // Modify Rejected
                    e.Value = cell.ModifyRejected;
                    break;
                case 17: // exec qty
                    e.Value = cell.ExecQuantity;
                    break;
                case 18: // exec price
                    e.Value = ForgePrettyPrinter.Prices.Format(cell.ExecAveragePrice, i.TickSizeRule.Tick(cell.ExecAveragePrice) / 10.0);
                    e.ToolTip = string.Empty + cell.ExecAveragePrice;
                    break;
                case 19: // cancel qty
                    e.Value = cell.CancelQuantity;
                    break;
                case 20: // Remaining qty
                    e.Value = cell.RemainingQuantity;
                    break;
                case 21: // status
                    e.Value = "Modify";
                    (this.virtualgrid[e.ColumnIndex, e.RowIndex] as DataGridViewDisableButtonCell).Enabled = cell.Alive;
                    break;
                case 22: // status
                    e.Value = "Cancel";
                    (this.virtualgrid[e.ColumnIndex, e.RowIndex] as DataGridViewDisableButtonCell).Enabled = cell.Alive;
                    break;
            }
        }

        /// <summary>
        /// The virtualgrid_ ui grid query row count.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnVirtualgridUIGridQueryRowCount(object sender, VirtualGridEventArgs.QueryRowCount e)
        {
            e.RowCount = this.trackingCells.Keys.Count;
        }

        #endregion
    }
}